package masterjava.common.logging;

import masterjava.common.settings.AppProps;
import masterjava.common.shared.logging.AbstractLogger;
import masterjava.common.shared.logging.LoggingLevel;
import masterjava.common.util.Util;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.jetbrains.annotations.Nullable;

import java.util.Map;

/**
 * User: GKislin
 * Date: 29.01.11
 */
public class ServerLogger extends AbstractLogger {

    @SuppressWarnings("unchecked")
    private static Map<LoggingLevel, Level> LEVEL_MAP = (Map<LoggingLevel, Level>)
            Util.asEnumMap(LoggingLevel.class,
                    LoggingLevel.TRACE, Level.TRACE, //The TRACE Level designates finer-grained informational events than the DEBUG
                    LoggingLevel.DEBUG, Level.DEBUG, // The DEBUG Level designates fine-grained informational events that are most useful to debug an application.
                    LoggingLevel.INFO, Level.INFO, // The INFO level designates informational messages that highlight the progress of the application at coarse-grained level.
                    LoggingLevel.WARN, Level.WARN, //The WARN level designates potentially harmful situations.
                    LoggingLevel.ERROR, Level.ERROR, // The ERROR level designates error events that might still allow the application to continue running.
                    LoggingLevel.FATAL, Level.FATAL); //The FATAL level designates very severe error events that will presumably lead the application to abort.

    private final Logger logger;

    @Override
    public void log(LoggingLevel logLevel, CharSequence msg, Throwable t) {
        logger.log(LEVEL_MAP.get(logLevel), msg, t);
    }

    private ServerLogger(Class clazz) {
        logger = Logger.getLogger(clazz);
    }

    public static ServerLogger get(Class clazz) {
        return new ServerLogger(clazz);
    }

    @Override
    public void treatThrowable(String msg, Throwable e) throws Error, RuntimeException {
        error(msg, e);
        if (e instanceof Error) {
            throw (Error) e;
        } else if (e instanceof RuntimeException) {
            throw (RuntimeException) e;
        } else {
            throw new IllegalStateException(msg, e);
        }
    }

    public static void setRootLoggingLevel(LoggingLevel value) {
        org.apache.log4j.Logger.getRootLogger().setLevel(LEVEL_MAP.get(value));
    }

    public IllegalStateException getIllegalStateException(String msg) {
        return getIllegalStateException(msg, null);
    }

    public IllegalStateException getIllegalStateException(String msg, @Nullable Throwable e) {
        error(msg, e);
        return new IllegalStateException(msg, e);
    }

    public IllegalArgumentException getIllegalArgumentException(String msg) {
        return getIllegalArgumentException(msg, null);
    }

    public IllegalArgumentException getIllegalArgumentException(String msg, @Nullable Throwable e) {
        error(msg, e);
        return new IllegalArgumentException(msg, e);
    }

    public UnsupportedOperationException getUnsupportedOperationException(String msg) {
        error(msg);
        return new UnsupportedOperationException(msg);
    }

    public static boolean isDebug() {
        return isEnabled(LoggingLevel.DEBUG);
    }

    public static boolean isEnabled(LoggingLevel level) {
        return AppProps.LOGGING_LEVEL.getValue().ordinal() <= level.ordinal();
    }

    public static void reset() {
        org.apache.log4j.Logger.getRootLogger().removeAllAppenders();
        BasicConfigurator.configure();
    }
}
